package cn.nn200433.job.config;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.ConsoleTable;
import cn.nn200433.job.executor.impl.XxlJobPlusSpringExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;

/**
 * XXL-JOB 分布式任务调度平台 执行器配置
 *
 * <p>
 * https://www.xuxueli.com/xxl-job/#%E6%AD%A5%E9%AA%A4%E4%BA%8C%EF%BC%9A%E6%89%A7%E8%A1%8C%E5%99%A8%E9%85%8D%E7%BD%AE
 * </p>
 *
 * @author nn200433
 * @date 2021年11月17日 0017 17:43:54
 */
@Slf4j
@Import(value = cn.hutool.extra.spring.SpringUtil.class)
@EnableConfigurationProperties(value = {XxlJobProperties.class})
public class XxlJobAutoConfig {

    /**
     * xxl-job执行器
     *
     * @param properties 特性
     * @return {@link XxlJobPlusSpringExecutor }
     * @author nn200433
     */
    @Bean
    @ConditionalOnProperty(prefix = XxlJobProperties.XXL_JOB_CONFIG_PREFIX, name = "enable", havingValue = "true")
    public XxlJobPlusSpringExecutor xxlJobExecutor(XxlJobProperties properties) {
        final AdminProperties    admin       = properties.getAdmin();
        final ExecutorProperties executor    = properties.getExecutor();
        final String             accessToken = properties.getAccessToken();
        System.out.println(buildConsoleTable(admin, executor, accessToken).toString());
        // 构建XxlJob执行器
        XxlJobPlusSpringExecutor xxlJobSpringExecutor = new XxlJobPlusSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(admin.getAddresses());
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setAddress(executor.getAddress());
        xxlJobSpringExecutor.setAppname(executor.getAppname());
        xxlJobSpringExecutor.setIp(executor.getIp());
        xxlJobSpringExecutor.setPort(executor.getPort());
        xxlJobSpringExecutor.setLogPath(executor.getLogpath());
        xxlJobSpringExecutor.setLogRetentionDays(executor.getLogretentiondays());
        return xxlJobSpringExecutor;
    }

    /**
     * 构建控制台表
     *
     * @param admin       调动中心配置
     * @param executor    执行器配置
     * @param accessToken 令牌
     * @return {@link ConsoleTable }
     * @author nn200433
     */
    private ConsoleTable buildConsoleTable(final AdminProperties admin, final ExecutorProperties executor,
                                           final String accessToken) {
        return ConsoleTable.create().addHeader("名称", "值", "描述")
                .addBody("调度中心地址", admin.getAddresses(), "选填，如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行\"执行器心跳注册\"和\"任务结果回调\"；为空则关闭自动注册；")
                .addBody("执行器（AppName）", executor.getAppname(), "选填，执行器心跳注册分组依据；为空则关闭自动注册")
                .addBody("执行器通讯令牌（TOKEN）", accessToken, "选填，非空时启用；")
                .addBody("执行器注册地址", executor.getAddress(), "选填，优先使用该配置作为注册地址，为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。")
                .addBody("执行器 IP", executor.getIp(), "选填，默认为空表示自动获取IP，多网卡时可手动设置指定IP，该IP不会绑定Host仅作为通讯实用；地址信息用于 \"执行器注册\" 和 \"调度中心请求并触发任务\"；")
                .addBody("执行器 PORT", Convert.toStr(executor.getPort()), "选填，小于等于0则自动获取；默认端口为9999，单机部署多个执行器时，注意要配置不同执行器端口；")
                .addBody("日志文件存储路径", executor.getLogpath(), "选填，需要对该路径拥有读写权限；为空则使用默认路径；")
                .addBody("日志文件保存天数", Convert.toStr(executor.getLogretentiondays()), "选填，过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能；");
    }

}
